/*
 * SceneGraphController.hpp
 *
 *  Created on: May 4, 2009
 *      Author: asantos
 */

class SceneGraphAlreadyExists : public virtual std::exception{
public:
	SceneGraphAlreadyExists(const char* msg){

	}
	char const* what()const throw(){
		return "SceneGraphAlreadyExists";
	}
};
class SceneGraphDoesNotExist : public virtual std::exception{
private:
		const char* msg;
public:
	SceneGraphDoesNotExist(const char* msg):msg(msg){

	}
	char const* what()const throw(){
		return msg;
	}
};

class SceneGraphController{
public:
	typedef void(GetSceneGraphControllerHandler)(SceneGraphController&);
	typedef void(GetSelectedSceneGraphHandler)(SceneGraph&);
	typedef std::map<std::string, SceneGraph*> SceneGraphs_Tp;
private:

	SignalBroker& signalbroker;
	SceneGraphs_Tp scenegraphs;
	SceneGraph* selectedscenegraph;
	Signal<GetSceneGraphControllerHandler>& getscenegraphcontroller;
	Signal<GetSelectedSceneGraphHandler>& getselectedscenegraph;

public:
	SceneGraphController(SignalBroker& signalbroker):
		signalbroker(signalbroker),
		selectedscenegraph(0),
		getscenegraphcontroller(signalbroker.CreateOrGetExistingSignal<GetSceneGraphControllerHandler>("/scenegraphcontroller/get")),
		getselectedscenegraph(signalbroker.CreateOrGetExistingSignal<GetSelectedSceneGraphHandler>("/scenegraphcontroller/getselectedscenegraph")){
		//bind GetSelectedSceneGraph to /clock/tick
		//any observer that wants the selected scenegraph can access it through
		// /scenegraphcontroller/getselectedscenegraph
		Signal<ClockView::TickHandler>& clocktick = signalbroker.CreateOrGetExistingSignal<ClockView::TickHandler>("/clock/tick");
		clocktick.connect(boost::bind(&SceneGraphController::GetSelectedSceneGraph, this, _1, _2));
		clocktick.connect(boost::bind(&SceneGraphController::GetSceneGraphController, this, _1, _2));

	}
	SceneGraph& CreateSceneGraph(const std::string& name){
		SceneGraph* scenegraph = 0;
		if(scenegraphs.find(name)==scenegraphs.end()){
			scenegraph = new SceneGraph();
			scenegraphs.insert(SceneGraphs_Tp::value_type(name, scenegraph));
			if(selectedscenegraph == 0){
				selectedscenegraph = scenegraph;
			}
			return *scenegraph;
		}
		else{
			throw SceneGraphAlreadyExists(name.c_str());
		}
	}
	void DeleteSceneGraph(const std::string& name){
		if(scenegraphs.find(name)!=scenegraphs.end()){
			delete scenegraphs.find(name)->second;
			scenegraphs.erase(name);
		}
		else{
			throw  SceneGraphDoesNotExist(name.c_str());
		}
	}
	void SelectSceneGraph(const std::string& name){
		if(scenegraphs.find(name)==scenegraphs.end()){
			selectedscenegraph = scenegraphs.find(name)->second;
		}else{
			throw SceneGraphAlreadyExists(name.c_str());
		}
	}
	void GetSelectedSceneGraph(long t, long dt){
		if(selectedscenegraph){
			getselectedscenegraph(*selectedscenegraph);
		}
	}
	SceneGraph& GetSelectedSceneGraph()const{
		return *selectedscenegraph;
	}
	void GetSceneGraphController(long t, long dt){
		getscenegraphcontroller(*this);
	}

};
